package com.bwie.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.bwie.common.constants.JwtConstants;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.domain.request.LoginRequest;
import com.bwie.common.domain.response.JwtResponse;
import com.bwie.common.domain.response.UserInfo;
import com.bwie.common.exctption.BizException;
import com.bwie.common.result.Result;
import com.bwie.common.utils.JwtUtils;
import com.bwie.remote.SysUserRemote;
import com.bwie.service.AuthService;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 登录业务处理层
 *
 * @author <a href="mailto:2891704036@qq.com">zhiyuheng</a>
 * @version 1.0
 * @description: 登录业务处理层
 * @date 2025/9/9 9:47
 */
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private SysUserRemote sysUserRemote;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 发送验证码
     * @param phone
     */
    @Override
    public void sendCode(String phone) {
        //手机号正则校验
        if (!phone.matches("1[3-9]\\d{9}")){
            throw new BizException("手机号格式错误，请重新输入！");
        }

        //先判断是否能发送，如果失败次数大于3次不能发送
        Boolean b1 = redisTemplate.hasKey("CANNOT_LOGIN" + phone);
        if (b1){
            throw new BizException("失败次数过多，5分钟后再试吧！");
        }

        //判断手机号是否注册
        Result<UserInfo> result = sysUserRemote.findByPhone(phone);
        //获取响应数据
        UserInfo userInfo = result.getData();
        //判空
        if (ObjectUtil.isEmpty(userInfo)){
            //发送失败自增
            redisTemplate.opsForValue().increment("SEND_FREQUENCY" + phone);
            //从redis中获取自增的次数
            Integer frequency = (Integer) redisTemplate.opsForValue().get("SEND_FREQUENCY" + phone);
            //判断如果大于3次
            if (frequency >= 3){
                //设置一个键五分钟内不能再发
                redisTemplate.opsForValue().set("CANNOT_LOGIN" + phone, "", 5, TimeUnit.MINUTES);
            }
            //抛异常
            throw new BizException("发送失败，该手机号还未注册");
        }

        //判断是否重复发送，获取发送成功后存在redis中的键
        Boolean b = redisTemplate.hasKey("SEND_COUNT" + phone);
        //如果存在则不能继续发送
        if (b){
            throw new BizException("5分钟内请勿重复发送！");
        }

        //生成验证码（4位验证码）
        String code = RandomUtil.randomNumbers(4);
        //验证码以手机号为key保存到redis当中，有效时间5分钟
        redisTemplate.opsForValue().set("SEND_CODE" + phone, code, 5, TimeUnit.MINUTES);
        //发送成功后，防止重复发送
        redisTemplate.opsForValue().set("SEND_COUNT" + phone, "", 5, TimeUnit.MINUTES);
    }

    /**
     * 登录
     * @param loginRequest
     * @return
     */
    @Override
    public JwtResponse login(LoginRequest loginRequest) {
        //先获取前端传的值
        String phone = loginRequest.getPhone();
        String code = loginRequest.getCode();

        //手机号正则校验
        if (!phone.matches("1[3-9]\\d{9}")){
            throw new BizException("手机号格式错误，请重新输入！");
        }

        //判断手机号是否注册
        Result<UserInfo> result = sysUserRemote.findByPhone(phone);
        //获取响应数据
        UserInfo userInfo = result.getData();
        //判空
        if (ObjectUtil.isEmpty(userInfo)){
            //抛异常
            throw new BizException("该手机号还未注册，请先注册！");
        }

        //判断验证码是否正确，先获取存在redis中的验证码
        String phoneCode = (String) redisTemplate.opsForValue().get("SEND_CODE" + phone);
        //比较是否正确
        if (!phoneCode.equals(code)){
            throw new BizException("验证码输入错误");
        }

        //登陆成功，开始存token
        Map<String,Object> map = new HashMap<>();
        //获取用户标识
        String userKey = IdUtil.randomUUID();
        //存用户标识
        map.put(JwtConstants.USER_KEY,userKey);
        //获取token
        String token = JwtUtils.createToken(map);
        //用户信息存redis
        redisTemplate.opsForValue().set(TokenConstants.LOGIN_TOKEN_KEY + userKey, userInfo, 30, TimeUnit.MINUTES);

        //返回JWT
        JwtResponse jwtResponse = new JwtResponse();
        //存token
        jwtResponse.setToken(token);
        //存过期时间
        jwtResponse.setExpireTime("30MIN");
        return jwtResponse;
    }
}
